/* DictionaryValue.cs --
   Copyright (C) 2008  Pacific Biosciences, Inc. */


using System;
using System.Collections.Generic;

namespace SexpSharp.RPC
{
	public class DictionaryValue : IValue
	{
		internal IDictionary<IValue, IValue> _value;

		public DictionaryValue(Expression e)
		{
			List list = e as List;
			if (list == null)
				throw new ArgumentException("must be a list", "e");
			if (list.Count < 1)
				throw new ArgumentException("list must have at least one atom");
			Atom name = list.First as Atom;
			if (name == null)
				throw new ArgumentException("first element must be an atom");
			if (!name.ToString().Equals(Values.DictName))
				throw new ArgumentException("first element must be `" + Values.DictName + "'");
			_value = new Dictionary<IValue, IValue>();
			foreach (Expression expr in list.Rest)
			{
				List pair = expr as List;
				if (pair == null || pair.Count != 2)
					throw new ArgumentException("expecting a pair");
				IValue key = Values.ExpressionToValue(pair.First);
				IValue value = Values.ExpressionToValue(pair.Second);
				_value[key] = value;
			}
		}

		public DictionaryValue(IDictionary<IValue, IValue> value)
		{
			value.GetType();
			this._value = value;
		}

		public DictionaryValue() : this(new Dictionary<IValue, IValue>())
		{
		}

		public IDictionary<IValue, IValue> Value
		{
			get { return _value; }
			set { value.GetType(); _value = value; }
		}

		public Expression ToExpression()
		{
			List l = new List();
			l.Add(new Atom(Values.DictName));
			foreach (KeyValuePair<IValue, IValue> e in _value)
			{
				List pair = new List();
				pair.Add(e.Key.ToExpression());
				pair.Add(e.Value.ToExpression());
				l.Add(pair);
			}
			return l;
		}

		public bool Equals(IValue that)
		{
			if (that is DictionaryValue)
			{
				IDictionary<IValue, IValue> val = ((DictionaryValue) that)._value;
				if (val.Count != _value.Count)
					return false;
				foreach (KeyValuePair<IValue, IValue> e in _value)
				{
					if (!val.ContainsKey(e.Key))
						return false;
					if (!e.Value.Equals(val[e.Key]))
						return false;
				}
				return true;
			}
			return false;
		}

		public override bool Equals(object o)
		{
			if (o is IValue)
				return Equals((IValue) o);
			return false;
		}

		public override int GetHashCode()
		{
			int code = 0;
			foreach (KeyValuePair<IValue, IValue> e in _value)
			{
				code ^= e.Key.GetHashCode();
				code ^= e.Value.GetHashCode();
			}
			return code;
		}
	}
}